package com.weixin.common.sftp;

import com.jcraft.jsch.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * sftp client
 *
 * @author zh
 */
public class SftpClient {

    private static final Log log = LogFactory.getLog(SftpClient.class);
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final AtomicLong CLIENT_NUMBER = new AtomicLong(1L);
    private final ChannelSftp channelSftp;
    private final Session session;

    private final String originalDir;

    public SftpClient(ClientProperties clientProperties) {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(clientProperties.getUsername(), clientProperties.getHost(), clientProperties.getPort());
            session.setPassword(clientProperties.getPassword());
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();
            originalDir = channelSftp.pwd();
            String clientInfo = "host:" + HostHolder.getHostName() + ",client:vcSftpClient" + +CLIENT_NUMBER.getAndIncrement() + ",createTime:" + DATE_TIME_FORMATTER.format(LocalDateTime.now());
            if (log.isInfoEnabled()) {
                log.info(clientInfo);
            }
        } catch (Exception e) {
            disconnect();
            throw new IllegalStateException("failed to create sftp Client", e);
        }
    }

    public ChannelSftp getChannelSftp() {
        return channelSftp;
    }

    public void disconnect() {
        if (session != null) {
            session.disconnect();
        }
    }

    static {
        JSch.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
    }

    protected boolean reset() {
        try {
            this.channelSftp.cd(this.originalDir);
            return true;
        } catch (SftpException e) {
            return false;
        }
    }

    public boolean validateConnect() {
        try {
            return session.isConnected() && channelSftp.isConnected() && originalDir.equals(channelSftp.pwd());
        } catch (Exception e) {
            return false;
        }
    }
}

